package com.ship.dispatch.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.ship.common.business.service.impl.BaseServiceImpl;
import com.ship.dispatch.bean.HomePage.ConHomePage;
import com.ship.dispatch.bean.ConShipping;
import com.ship.dispatch.bean.SpPortInformation;
import com.ship.dispatch.bean.SpShipAgencyFeeHistory;
import com.ship.dispatch.bean.treaShipNetwork.IhsShipBase;
import com.ship.dispatch.bean.treaShipNetwork.IhsShipBaseShipVo;
import com.ship.dispatch.mapper.ConShippingMapper;
import com.ship.dispatch.mapper.SpPortInformationMapper;
import com.ship.dispatch.mapper.SpShipAgencyFeeHistoryMapper;
import com.ship.dispatch.mapper.treaShipNetwork.IhsShipBaseMapper;
import com.ship.dispatch.service.ConHomePageServer;
import com.ship.dispatch.service.ConShippingService;
import com.ship.dispatch.vo.PortInformationVo;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class ConShippingServiceImpl extends BaseServiceImpl<ConShippingMapper, ConShipping> implements ConShippingService {

    @Autowired
    private SpPortInformationMapper portInformationMapper;
    @Autowired
    private IhsShipBaseMapper ihsShipBaseMapper;
    @Autowired
    private SpShipAgencyFeeHistoryMapper spShipAgencyFeeHistoryMapper;
    @Autowired
    private ConHomePageServer conHomePageServer;

    @Override
    public List<IhsShipBase> getIhsShipBases(String name) {
        if (StringUtils.isNotBlank(name)) {
            name = name.toUpperCase();
        }
        List<IhsShipBase> ihsShipBases = ihsShipBaseMapper.selectList(new LambdaQueryWrapper<IhsShipBase>().likeRight(StringUtils.isNotBlank(name), IhsShipBase::getShipName, name));
        return ihsShipBases;
    }

    /**
     * 船舶名称筛选船舶租金信息
     *
     * @param ihsShipBases
     * @return
     */
    @Override
    public List<IhsShipBaseShipVo> getIhsShipRentInfo(List<IhsShipBase> ihsShipBases) {
        List<IhsShipBaseShipVo> shipBaseVos = new ArrayList<>();
        if (null != ihsShipBases && ihsShipBases.size() > 0) {
            ihsShipBases.stream().forEach(i -> {
                IhsShipBaseShipVo ihsShipBaseVo = new IhsShipBaseShipVo();
                BeanUtils.copyProperties(i, ihsShipBaseVo);
                List<ConShipping> conShippings = this.list(new LambdaQueryWrapper<ConShipping>().eq(ConShipping::getImo, i.getImo()));
                if (null != conShippings && conShippings.size() > 0) {
                    ihsShipBaseVo.setRent(conShippings.get(0).getRent());
                }
                shipBaseVos.add(ihsShipBaseVo);
            });
        }
        return shipBaseVos;
    }

    /**
     * 接收站带出该接收站下的历史平均船代费
     *
     * @param name    接收站
     * @param feeType 1：装载，2：卸载
     * @return
     */
    @Override
    public List<PortInformationVo> getShipAgencyFee(String name, Integer feeType) {
        List<PortInformationVo> portInformationVos = new ArrayList<>();
        if (StringUtils.isNotBlank(name)) {
            name = name.toUpperCase();
        }
        List<SpPortInformation> portInformations = portInformationMapper.selectList(new LambdaQueryWrapper<SpPortInformation>()
                .likeRight(StringUtils.isNotBlank(name), SpPortInformation::getPortNameEnglish, name)
                .eq(SpPortInformation::getPortType, 2));

        if (null != portInformations && portInformations.size() > 0) {
            portInformations.stream().forEach(p -> {
                List<SpShipAgencyFeeHistory> spShipAgencyFeeHistorys = spShipAgencyFeeHistoryMapper.selectList(new LambdaQueryWrapper<SpShipAgencyFeeHistory>()
                        .eq(SpShipAgencyFeeHistory::getName, p.getPortNameEnglish())
                        .eq(SpShipAgencyFeeHistory::getFeeType, feeType));
                PortInformationVo portInformationVo = new PortInformationVo();
                portInformationVo.setName(p.getPortNameEnglish());
                if (null != spShipAgencyFeeHistorys && spShipAgencyFeeHistorys.size() > 0) {
                    Integer num = spShipAgencyFeeHistorys.size();
                    if (1 == spShipAgencyFeeHistorys.get(0).getFeeType()) {
                        BigDecimal expectedLoadingFees = spShipAgencyFeeHistorys.stream().filter(s -> null != s.getExpectedLoadingFee()).map(SpShipAgencyFeeHistory::getExpectedLoadingFee).reduce(BigDecimal.ZERO, BigDecimal::add);
                        portInformationVo.setExpectedFee(expectedLoadingFees.divide(new BigDecimal(num), 2, RoundingMode.DOWN));
                    } else if (2 == spShipAgencyFeeHistorys.get(0).getFeeType()) {
                        BigDecimal expectedUnloadingFees = spShipAgencyFeeHistorys.stream().filter(s -> null != s.getExpectedUnloadingFee()).map(SpShipAgencyFeeHistory::getExpectedUnloadingFee).reduce(BigDecimal.ZERO, BigDecimal::add);
                        portInformationVo.setExpectedFee(expectedUnloadingFees.divide(new BigDecimal(num), 2, RoundingMode.DOWN));
                    }
                }
                portInformationVos.add(portInformationVo);
            });
        }
        return portInformationVos;
    }

    @Override
    public Integer queryRentShipNumber(String endDate) {
        List<ConShipping> conShippingList = baseMapper.queryRentShipNumber(endDate);
        if (CollectionUtil.isNotEmpty(conShippingList)) {
            Map<String, List<ConShipping>> collect = conShippingList.stream().collect(Collectors.groupingBy(ConShipping::getShipName));
            return collect.size();
        }
        return 0;
    }

    @Override
    public Integer queryTransportShipNumber() {

        return baseMapper.queryTransportShipNumber();
    }

    /**
     * 定时任务，保存当前可用船只，每小时
     */
    @Override
    public void setShipImo() {
        //获取当球数据
        List<ConShipping> conShippingList = this.baseMapper.getShipImo();

        //筛选相同imo当中，最接近当前时间的，用交船日期-开始判断
        Map<String, ConShipping> closestRecords = new HashMap<>();
        for (ConShipping record : conShippingList) {
            closestRecords.merge(
                    record.getImo(),
                    record,
                    (existing, current) -> {
                        long existingDiff = Math.abs(existing.getDeliveryDateBegin().getTime() - System.currentTimeMillis());
                        long currentDiff = Math.abs(current.getDeliveryDateBegin().getTime() - System.currentTimeMillis());
                        return existingDiff <= currentDiff ? existing : current;
                    }
            );
        }

        List<ConHomePage> conHomePageList = closestRecords.values().stream()
                .map(record -> {
                    ConHomePage homePage = new ConHomePage();
                    homePage.setConId(record.getId());
                    homePage.setImo(record.getImo());
                    homePage.setDeliveryDateBegin(record.getDeliveryDateBegin());
                    homePage.setRedeliveryDateEnd(record.getRedeliveryDateEnd());
//                    homePage.setPrimeMoverDescriptiveNarrative(record.getPrimeMoverDescriptiveNarrative());
//                    homePage.setCabinCapacity(record.getCabinCapacity());
//                    homePage.setEvaporationRate(record.getEvaporationRate());
//                    homePage.setEmptyEvaporationRate(record.getEmptyEvaporationRate());
//                    homePage.setAisStatus("default"); 状态从pgsql里面来
                    return homePage;
                })
                .collect(Collectors.toList());
        //清理历史数据
        this.baseMapper.clearTable();
        conHomePageServer.insetOrUpdateByImo(conHomePageList);

    }

    /**
     * 根据可用船只的imo，从pgsql获取ais状态并保存
     */
    @Override
    public void setImoStatus() {
        //获取可用船只的imo
        List<String> imoList = conHomePageServer.getAllImo();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
        String tableSuffix = sdf.format(new Date());
        String tableName = "boats_ais_message" + tableSuffix;
        List<ConHomePage> conHomePageList = conHomePageServer.getAisStatus(imoList, tableName);
        this.baseMapper.updateByImo(conHomePageList);
    }

    @Override
    public List<ConHomePage> getImoStatus() {
        return conHomePageServer.getAll();
    }
}
